﻿using log4net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace WebApplication3.Controllers
{
    public class WeiXinController : Controller
    {
        private static readonly ILog logger = LogManager.GetLogger(typeof(WeiXinController));
        private static string Token = "yshcyt";
        
        public ActionResult Index()
        {

            //CustomSendMessage("oisyXwVd5muVvkSAF2q3Tl3Ib8Xc", "hello");
            string signature = Request.QueryString["signature"];
            string timestamp = Request.QueryString["timestamp"];
            string nonce = Request.QueryString["nonce"];
            string echostr = Request.QueryString["echostr"]; 

            Core.Log.Info($"WeiXinController/Index?signature={signature}&timestamp={timestamp}&nonce={nonce}&echostr={echostr}");
            if (WeiXinController.Check(signature, timestamp, nonce, Token))
            {

                Response.Write(echostr);
                Response.End();

                Core.Log.Info("开始执行按钮事件");

                string postString = string.Empty;
                Core.Log.Info($"HttpContext.Request.HttpMethod.ToUpper()={HttpContext.Request.HttpMethod.ToUpper()}");
                if (HttpContext.Request.HttpMethod.ToUpper() == "POST")
                {
                    using (Stream stream = HttpContext.Request.InputStream)
                    {
                        //获取微信提交过来的参数
                        Byte[] postBytes = new Byte[stream.Length];
                        stream.Read(postBytes, 0, (Int32)stream.Length);
                        postString = Encoding.UTF8.GetString(postBytes); 
                        Core.Log.Info($"postString={postString}");
                        //对其进行处理
                        MenuMessage(postString);
                    }
                }
                return Content(echostr);//返回随机字符串则表示验证通过
            }
            else
            {
                return null;
                //return Content("failed:" + signature + "," + WeiXinController.GetSignature(timestamp, nonce, Token) + "。如果你在浏览器中看到这句话，说明此地址可以被作为微信公众账号后台的Url，请注意保持Token一致。");
            }
        }
        /// <summary>
        /// 检查签名是否正确
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool Check(string signature, string timestamp, string nonce, string token = null)
        {
            var mySignature = GetSignature(timestamp, nonce, token);
            var falg = signature == mySignature;
            Core.Log.Info($"signature={signature}，mySignature={mySignature}，falg={falg}");
            return falg;
        }
        /// <summary>
        /// 返回正确的签名
        /// </summary>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static string GetSignature(string timestamp, string nonce, string token = null)
        {
            token = token ?? Token;
            var arr = new[] { token, timestamp, nonce }.OrderBy(z => z).ToArray();
            var arrString = string.Join("", arr);
            var sha1 = System.Security.Cryptography.SHA1.Create();
            var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
            StringBuilder enText = new StringBuilder();
            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }
            return enText.ToString();
        }



        #region 处理应答消息
        /// <summary>
        /// 处理应答消息
        /// </summary>
        /// <param name="postStr">微信提交过来的参数</param>
        /// <returns></returns>
        public static string MenuMessage(string postStr)
        {
            string responseContent = "";
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(new System.IO.MemoryStream(System.Text.Encoding.GetEncoding("GB2312").GetBytes(postStr)));
            XmlNode MsgType = xmldoc.SelectSingleNode("/xml/MsgType");

            if (MsgType != null)
            {
                switch (MsgType.InnerText)
                {
                    case "event": 
                        responseContent = MenuEventHandle(xmldoc);//事件处理

                        break;
                    case "text"://接受文本消息
                        //< xml >
                        //< ToUserName >< ![CDATA[gh_63df81f0364b]] ></ ToUserName >
                        //< FromUserName >< ![CDATA[oisyXwVd5muVvkSAF2q3Tl3Ib8Xc]] ></ FromUserName >
                        //< CreateTime > 1525416752 </ CreateTime >
                        //< MsgType >< ![CDATA[text]] ></ MsgType >
                        //< Content >< ![CDATA[你好]] ></ Content >
                        //< MsgId > 6551615063057992997 </ MsgId >
                        //</ xml > 
                        break;
                    default:
                        break;
                }
            }
            return responseContent;
        }

        #endregion

        /// <summary>
        /// 事件处理
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <returns></returns>
        public static string MenuEventHandle(XmlDocument xmldoc)
        {
            string responseContent = ""; 
            XmlNode MsgType = xmldoc.SelectSingleNode("/xml/MsgType");//消息类型
            XmlNode Event = xmldoc.SelectSingleNode("/xml/Event");//事件类型，CLICK
            XmlNode EventKey = xmldoc.SelectSingleNode("/xml/EventKey");//事件KEY值，与自定义菜单接口中KEY值对应
            XmlNode ToUserName = xmldoc.SelectSingleNode("/xml/ToUserName");//开发者微信号
            XmlNode FromUserName = xmldoc.SelectSingleNode("/xml/FromUserName");//发送方账号一个openid
            XmlNode CreateTime = xmldoc.SelectSingleNode("/xml/CreateTime");
            XmlNode Ticket = xmldoc.SelectSingleNode("/xml/Ticket");
            Core.Log.Info($"ToUserName={ToUserName.InnerText},FromUserName={FromUserName.InnerText},CreateTime={CreateTime.InnerText},MsgType={MsgType.InnerText},Event={Event.InnerText},EventKey={EventKey.InnerText},Ticket={Ticket.InnerText}");

            if (Event != null)
            {
                //菜单单击事件
                if (Event.InnerText.Equals("CLICK"))
                {
                    if (EventKey.InnerText.Equals("V1001_01"))//可以进行相关内容的实现，如发送自定义的动态消息
                    {
                        Core.Log.Info("Event=" + Event + ";EventKey=" + EventKey + ";ToUserName=" + ToUserName + ";FromUserName=" + FromUserName + "。");
                        //SendNewsMsg(FromUserName.InnerText, "进度提醒", "描述！", "", "");
                    }
                }
                //二维码扫描事件
                else if(Event.InnerText.Equals("SCAN"))
                {
                    SCANorSubscribe(FromUserName.InnerText, EventKey.InnerText);
                    Core.Log.Info("二维码扫描事件");
                }
                //关注公众号
                else if (Event.InnerText.Equals("subscribe"))
                {
                    var wxid = EventKey.InnerText.TrimStart("qrscene_".ToArray()); //如果是关注公众号事件，微信会在参数前面加上 qrscene_  ，所以要把前缀去掉
                    SCANorSubscribe(FromUserName.InnerText, wxid);
                    Core.Log.Info("关注公众号");
                }
                //取消关注
                else if (Event.InnerText.Equals("unsubscribe"))
                {
                }
            }
            return responseContent;
        }
        /// <summary>
        /// 关注公众号处理
        /// </summary>
        /// <param name="xmldoc"></param>
        /// <returns></returns>
        public static string SubscribeHandle(XmlDocument xmldoc)
        {
            string responseContent = ""; 
            return responseContent;
        }

        /// <summary>
        /// 发送客服消息
        /// </summary>
        /// <returns></returns>
        public static string CustomSendMessage(string OPENID, string msg)
        {
            //var asdkfj2 = "已为您成功创建彩印通账号：账号open_wieur39，密码lksdfiejfa。点击登录PC网页，2分钟内有效<a href='http://www.kiy.cn/'>>>>点击立即登录彩印通网页</a>";
            //var asdkfj3 = "点击登录PC网页，2分钟内有效<a href='http://www.kiy.cn/'>>>>点击立即登录彩印通网页</a>";
            //var asdkfj = "<a href='http://www.qq.com'>点击跳小程序</a>";  
            var param = "{ \"touser\":\"" + OPENID + "\", \"msgtype\":\"text\", \"text\": { \"content\":\""+ msg + "\" } }";
            var url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + MvcApplication.MyToken;
            var fefe = Core.Helper.HttpHelper.Post(url, param);
            return param; 
        }

        /// <summary>
        /// 扫描或关注的处理
        /// </summary>
        /// <param name="openId"></param>
        /// <param name="scene_id"></param>
        /// <returns></returns>
        public static string SCANorSubscribe(string openId,string scene_id)
        {
            var msg = "";
            //验证scene_id
            //将scene_id标记为已经扫码,储存openid
            var wxModel = MvcApplication.listWxModel.FirstOrDefault(x => x.scene_id == scene_id);
            if (wxModel == null) return null;
            wxModel.openId = openId;
            wxModel.isscan = true;
            wxModel.scanTime = DateTime.Now;
             
            var asdf = MvcApplication.listWxModel.FirstOrDefault(x => x.scene_id == scene_id);
            Core.Log.Info($"isscan={asdf.isscan},scanTime={asdf.scanTime},openId={asdf.openId}");
             
            //openid检查FromUserName是否已经存在
            if (openId == "oisyXwVd5muVvkSAF2q3Tl3Ib8Xc")//已经存在，已经注册
            {
                //msg = "点击登录PC网页，2分钟内有效<a href='http://www.kiy.cn/'>>>>点击立即登录彩印通网页</a>";
                msg = "恭喜您，成功扫码登录！";
            }
            else//不存在,未注册
            {
                //注册新用户
                msg = "已为您成功创建彩印通账号：账号open_wieur39，密码lksdfiejfa。点击登录PC网页，2分钟内有效<a href='http://www.kiy.cn/'>>>>点击立即登录彩印通网页</a>";
            }
            CustomSendMessage(openId, msg); 
            return null;
        }

    }
}